import Vue from 'vue';
import Aegis from 'aegis-web-sdk';

import Cookies from 'js-cookie';
import { v4 as uuidv4 } from 'uuid';
import { getUserCategory } from '@/utils';
import { HISTORY_COUNT, MESSAGE_TYPE, APP_TYPE, WORD_LIMIT, ChatUserCategory } from '@/constants';
import {
    getQueryVariable,
    generateRequestId,
    arrayUnique,
    isJSON,
    isEmpty,
    getClarifyQuestion,
    getPreviewUrl,
    getFileIcon,
    getFileIconUrl
} from '@/utils/util';
import { getMsgRecord } from '@/api/modules/auth.js';
import clone from 'clone';

const $e = Vue.prototype.$eventHub;
const $s = Vue.prototype.$socket;
const webIMSource = Vue.prototype.webIMSource;

let cache = null; // 缓存
let timeoutTasks = {}; // 超时任务管理
const msgSendTimeout = 2 * 60 * 1000; // 发送消息超时ms，此处超时默认为2min
const systemEventsMax = 100; // 系统事件栈长度
const sessionClose = 'close_session'; // 结束会话

class ClientData {
    constructor() {
        cache = {
            appType: '', // 应用类型；knowledge_qa-知识问答管理；summary-知识摘要；classifys-知识标签提取
            session_id: '', // 会话ID
            configInfo: null, // 配置信息
            chatsContent: [], // 会话聊天内容
            systemEvents: [], // 系统事件栈
            AsyncParams: {},
            workflowParams: null, // 工作流调试状态，数据下行入参
            transferInfo: {
                transferStatus: false,
                transferAvatar: ''
            }, // 当前转人工状态
            pattern: '',
            singleWorkflow: null,
            userDialogConfig: {},
            readingInfo: {
                is_reading: false,
                record_id: ''
            }
        };
    }
    init() {
        // 获取基础配置
        this.queryConfigInfo();
        // 监听下行消息
        this.listenReplyMsg();
        // 监听token下行消息
        this.listenTokenStat();
        // 监听思考过程，agent模式
        this.listenThought();
        // 监听参考来源
        this.listenReference();
        // 监听推荐问
        this.listenRecommended();
        // 监听是否打开搜索引擎检索状态
        // this.listenShowSearchEngine();
        // 监听点赞/点踩回执
        this.listenFeedback();
        // 监听会话转接事件
        this.listenSessionTransfer();
        // 监听会话结束事件
        this.listenSessionClosed();
        // 监听重置事件
        this.listenSessionReset();
        // 监听ws报错
        this.listenError();
    }
    async updateAiConfig(aiConfig) {
        cache.configInfo.ai_call = aiConfig;
    }
    // 获取基础配置
    async queryConfigInfo() {
        try {
            // DescribeApp
            // 调用describeaApp
            if (window.webimToken && window.webimToken[0]) {
                cache.pattern = window.webimToken[0].pattern || '';
                cache.singleWorkflow = window.webimToken[0].single_workflow || null;
            }
            if (webIMSource === 'client') {
                let webimToken = window.webimToken[0];
                const appType = webimToken.app_type;
                const botBizId = webimToken.bot_biz_id || '';
                const seatBizId = webimToken.seat_biz_id || '';
                // console.log('appType--->', window.webimToken);
                cache.app_type = appType;
                window.localStorage.setItem('bot_biz_id_im', botBizId);
                window.localStorage.setItem('seat_biz_id_im', seatBizId);
                window.localStorage.setItem('app_type', appType);
                const { session_id } = await this.createSession();
                cache.seat_biz_id = seatBizId;
                cache.session_id = session_id;
                const result = {};
                result.AiCall = webimToken.ai_call;
                result.AsyncWorkflow = false;
                result.BotBizId = botBizId;
                result.ChatWordsLimit = 0;
                result.Greeting = webimToken.greeting;
                result.ImageSecurity = false;
                result.IsAvailable = true;
                result.Name = webimToken.name;
                result.RequestId = webimToken.request_id;
                result.TokenBalance = "221622"
                result.TokenTotal = "500000"
                const newResult = this.convertKeys(result)
                // 接着获取机器人基础信息
                cache.configInfo = { ...window.webimToken[0], ...newResult };
                cache.configInfo.session_id = session_id;
                $e.$emit('client_configChange', cache.configInfo);
            } 
        } catch (e) {
            Vue.prototype.$message.error('获取会话信息失败，请刷新页面重试！');
        }
    }
    async createSession() {
        let session_id = uuidv4();
        if(localStorage.getItem("thissessionid")){
            session_id = localStorage.getItem("thissessionid")
        }else{
            localStorage.setItem("thissessionid",session_id)
        }
        return { 'session_id': session_id };
    }
    async getWordCount(model) {
        try {
            if (webIMSource === 'client') {
                const webimToken = window.webimToken[0] || {};
                // console.log('webimToken', webimToken);
                return webimToken.input_len_limit || WORD_LIMIT;
            } else {
                const webimToken = window.webimToken[0] || {};
                return webimToken.input_len_limit || WORD_LIMIT;
            }
        } catch (error) {
            console.error(error);
            return WORD_LIMIT;
        }
    }
    // 获取全局配置信息
    setSearchNetworkPar(params) {
        // console.log('2800000000000000000 handleClickSearchNetwork=====>', params);
        cache.configInfo.search_network = params;
    }
    // 获取全局配置信息
    getSearchNetworkPar() {
        return cache.configInfo.search_network;
    }
    // 获取全局配置信息
    setWorkflowParams(params) {
        cache.workflowParams = params;
    }
    // 获取全局配置信息
    getWorkflowParams() {
        return cache.workflowParams;
    }
    // 获取全局配置信息
    setAsyncParams(params) {
        cache.AsyncParams = params;
    }
    // 获取全局配置信息
    getAsyncParams() {
        return cache.AsyncParams;
    }

    // 获取单工作流模式信息
    getPattern() {
        return {
            pattern: cache.pattern,
            singleWorkflow: cache.singleWorkflow
        };
    }
    // 获取全局配置信息
    getConfigInfo() {
        return cache.configInfo;
    }
    // 消息上行事件（用户端）
    async triggerSendMsg(msg, docUrls = []) {
        if (!cache.configInfo || !cache.configInfo.session_id) {
            await this.queryConfigInfo();
        }
        const requestId = generateRequestId();

        // 插入消息队列的数据
        const msgContent = {
            request_id: requestId,
            content: msg,
            file_infos: docUrls.map((i) => ({
                doc_id: i.doc_id,
                file_name: i.filename || i.file_name,
                file_type: i.filetype || i.file_type,
                file_size: i.filesize || i.file_size,
                file_url: cache.pattern === 'agent' ? i.file_url || i.url : i.url || i.file_url
            })),
            is_from_self: true,
            // timestamp: +new Date(),
            timestamp: Math.floor(+new Date() / 1000),
            is_final: true, // 问题无流失，默认置为 true（即流式输出已结束）
            is_loading: true // 默认消息发送中
        };
        // console.log('===============triggerSendMsg========', msgContent);
        // console.log('===============triggerSendMsg========config======', cache.configInfo);

        this.assembleMsgContent(msgContent, MESSAGE_TYPE.QUESTION);

        timeoutTasks[msgContent.request_id] = setTimeout(() => {
            this.assembleMsgContent(
                {
                    ...msgContent,
                    failed: true
                },
                MESSAGE_TYPE.ANSWER
            );
        }, msgSendTimeout);

        // 应用类型；knowledge_qa-知识问答管理；summary-知识摘要；classifys-知识标签提取
        let msgtype = '';
        if (cache.app_type === APP_TYPE.SUMMARY) {
            msgtype =
                webIMSource === 'client'
                    ? 'knowledge_summary'
                    : 'knowledge_summary_experience';
        } else if (cache.app_type === APP_TYPE.CLASSIFYS) {
            msgtype =
                webIMSource === 'client'
                    ? 'tag_extraction'
                    : 'tag_extraction_experience';
        } else {
            msgtype = 'send';
            $e.$emit('upwardmsg');
        }
        // console.log(msgtype,'msgtypemsgtypemsgtype')
        $s.emit(msgtype, {
            request_id: requestId,
            session_id: cache.configInfo ? cache.configInfo.session_id : 0,
            file_infos: docUrls.map((i) => ({
                doc_id: i.doc_id,
                file_name: i.filename || i.file_name,
                file_type: i.filetype || i.file_type,
                file_size: i.filesize || i.file_size,
                file_url: cache.pattern === 'agent' ? i.file_url || i.url : i.url || i.file_url
            })),
            search_network: cache.configInfo.search_network,
            content: msg,
            enable_multi_intent: true
        });
    }
    // 消息上行事件（后台体验端）
    async triggerSendExperienceMsg(msg, docUrls = [], isGenerateAgain = false) {
        if (!cache.configInfo || !cache.configInfo.session_id) {
            await this.queryConfigInfo();
        }
        const requestId = generateRequestId();

        // 插入消息队列的数据
        const msgContent = {
            request_id: requestId,
            content: msg,
            file_infos: docUrls.map((i) => ({
                doc_id: i.doc_id,
                file_name: i.filename || i.file_name,
                file_type: i.filetype || i.file_type,
                file_size: i.filesize || i.file_size,
                file_url: cache.pattern === 'agent' ? i.file_url || i.url : i.url || i.file_url
            })),
            is_from_self: true,
            // timestamp: +new Date(),
            timestamp: Math.floor(+new Date() / 1000),
            is_final: true, // 问题无流失，默认置为 true（即流式输出已结束）
            is_loading: true // 默认消息发送中
        };
        // console.log('===============triggerSendMsg========', msgContent);
        // console.log('00000000000000-------onSendQuestion------》', msg, picUrls, docUrls, msgContent);
        // console.log('poooooooooooooooost111111111-------send------->', this.getWorkflowParams(), cache.workflowParams);

        this.assembleMsgContent(msgContent, MESSAGE_TYPE.QUESTION);

        timeoutTasks[msgContent.request_id] = setTimeout(() => {
            this.assembleMsgContent(
                {
                    ...msgContent,
                    failed: true
                },
                MESSAGE_TYPE.ANSWER
            );
        }, msgSendTimeout);

        let msgtype = '';
        if (cache.app_type === APP_TYPE.SUMMARY) {
            // msgtype = 'knowledge_summary_experience';
            msgtype =
                webIMSource === 'client'
                    ? 'knowledge_summary'
                    : 'knowledge_summary_experience';
        } else if (cache.app_type === APP_TYPE.CLASSIFYS) {
            // msgtype = 'tag_extraction_experience';
            msgtype =
                webIMSource === 'client'
                    ? 'tag_extraction'
                    : 'tag_extraction_experience';
        } else {
            // if (docUrls) {
            // agent 演示 默认用 agent模式
            // msgtype = 'agent_experience';
            // } else {
            msgtype = 'experience';
            $e.$emit('upwardmsg');
            // }
        }
        let sendObj = {
            request_id: requestId,
            session_id: cache.configInfo ? cache.configInfo.session_id : 0,
            file_infos: docUrls.map((i) => ({
                doc_id: i.doc_id,
                file_name: i.filename || i.file_name,
                file_type: i.filetype || i.file_type,
                file_size: i.filesize || i.file_size,
                file_url: cache.pattern === 'agent' ? i.file_url || i.url : i.url || i.file_url
            })),
            search_network: cache.configInfo.search_network,
            content: msg,
            enable_multi_intent: true
        };
        if (webIMSource === 'workflow') {
            const workflowId = getQueryVariable('workflow_id');
            // console.log('【workflowId】', workflowId, cache.workflowParams);
            sendObj.workflow_id = workflowId;
            if (cache.workflowParams) {
                if (!isEmpty(cache.workflowParams.custom_variables)) {
                    sendObj.custom_variables = cache.workflowParams.custom_variables;
                }
                if (!isEmpty(cache.workflowParams.workflow_input)) {
                    sendObj.workflow_input = cache.workflowParams.workflow_input;
                }
            }
        } else {
            // const webimToken = window.webimToken[0] || {};
            // console.log('set custom_variables custom_variables createWorkflowRun params', cache.AsyncParams);
            sendObj.custom_variables = cache.AsyncParams;
            // if (webimToken.asy && webimToken.debug_mode === 1) {
            //     console.log('set custom_variables custom_variables createWorkflowRun params', cache.AsyncParams);
            //     sendObj.custom_variables = cache.AsyncParams;
            // } else {
            //     if (!isEmpty(cache.workflowParams.custom_variables)) {
            //         sendObj.custom_variables = cache.workflowParams.custom_variables;
            //     }
            // }
        }

        if (isGenerateAgain) {
            sendObj.generate_again = true;
        }
        $s.emit(msgtype, {
            ...sendObj
        });
        if (Vue.$aegis) {
            Vue.$aegis.infoAll({
                msg: `[socket event] experience`,
                level: Aegis.logType.INFO,
                ext1: `uin ${Cookies.get('username') || '-'}`,
                ext2: JSON.stringify({
                    request_id: requestId,
                    session_id: cache.configInfo ? cache.configInfo.session_id : 0,
                    file_infos: docUrls.map((i) => ({
                        doc_id: i.doc_id,
                        file_name: i.filename || i.file_name,
                        file_type: i.filetype || i.file_type,
                        file_size: i.filesize || i.file_size,
                        file_url: cache.pattern === 'agent' ? i.file_url || i.url : i.url || i.file_url
                    })),
                    content: msg
                })
            });
        }
    }
    // 触发点赞/点踩
    triggerScore(msgId, isThumbsUp) {
        const findedMsg = this.getMsgById(msgId);

        if (findedMsg) {
            findedMsg.score = isThumbsUp ? 1 : 2;
            findedMsg.reasons = [];
        }

        $s.emit('rating', {
            record_id: msgId,
            score: isThumbsUp ? 1 : 2, // 1. 点赞, 2. 点踩
            reasons: []
        });
        if (Vue.$aegis) {
            Vue.$aegis.infoAll({
                msg: `[socket event] rating`,
                level: Aegis.logType.INFO,
                ext1: `uin ${Cookies.get('username') || '-'}`,
                ext2: JSON.stringify({
                    record_id: msgId,
                    score: isThumbsUp ? 1 : 2, // 1. 点赞, 2. 点踩
                    reasons: []
                })
            });
        }
    }
    closeChatSession() {
        const oldestMsg = cache.chatsContent[0];
        // console.log('closeChatSession');
        $s.emit(sessionClose, {
            bot_biz_id: Number(cache.configInfo.bot_biz_id),
            session_id: cache.configInfo ? cache.configInfo.session_id : 0,
            last_record_id: oldestMsg ? oldestMsg.record_id : '' // 初始根据历史记录数量判断欢迎页展示逻辑场景，没有上一条会话id；其他会话场景向上滚动场景，可以获取到会话id
        });
        Vue.prototype.$message.tips('结束会话成功');
        if (Vue.$aegis) {
            Vue.$aegis.infoAll({
                msg: `[socket event] sessionClose`,
                level: Aegis.logType.INFO,
                ext1: `uin ${Cookies.get('username') || '-'}`,
                ext2: JSON.stringify({
                    bot_biz_id: Number(cache.configInfo.bot_biz_id),
                    session_id: cache.configInfo ? cache.configInfo.session_id : 0,
                    last_record_id: oldestMsg ? oldestMsg.record_id : '' // 初始根据历史记录数量判断欢迎页展示逻辑场景，没有上一条会话id；其他会话场景向上滚动场景，可以获取到会话id
                })
            });
        }
    }
    // 触发反馈
    triggerFeedback(msgId, reasons) {
        const findedMsg = this.getMsgById(msgId);

        if (findedMsg) {
            findedMsg.reasons = reasons;
        }

        $s.emit('rating', {
            record_id: msgId,
            score: 2,
            reasons
        });
        if (Vue.$aegis) {
            Vue.$aegis.infoAll({
                msg: `[socket event] rating`,
                level: Aegis.logType.INFO,
                ext1: `uin ${Cookies.get('username') || '-'}`,
                ext2: JSON.stringify({
                    record_id: msgId,
                    score: 2,
                    reasons
                })
            });
        }
    }
    // 监听ws下行答案消息
    listenReplyMsg() {
        $s.on('reply', (data) => {
            if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时，则不做处理
            const findedMsg = this.getMsgById(data.record_id);
            // console.log('0000000000000000ref   reply', data, findedMsg);
            if (findedMsg && findedMsg.is_final) return; // 若消息已经”停止生成“，则新消息抛弃
            // let copyData = data
            if (data.quote_infos && data.quote_infos.length > 0) {
                const quoteMock = data.quote_infos.reduce((acc, curr) => {
                    const existingItem = acc.find(item => item.position === curr.position);
                    let res = {};
                    if (findedMsg && findedMsg.references && findedMsg.references.length > 0) {
                        res = findedMsg.references.find(i => i.id === curr.index.toString());
                    }
                    if (existingItem) {
                        existingItem.tag.push({ ...res, id: curr.index });
                    } else {
                        acc.push({
                            'tag': [{ ...res, id: curr.index }],
                            'position': curr.position
                        });
                    }
                    return acc;
                }, []);

                data.quote_infos = quoteMock.sort((a, b) => b.position - a.position);

                // 遍历数组，对每个元素进行操作
                data.quote_infos.forEach(item => {
                    // 提取id数组并转换为字符串
                    const tagIds = item.tag.map(tag => tag.id);
                    const tagString = `[${tagIds.join(',')}](@ref)`;

                    // 在指定位置插入字符串
                    data.content = data.content.slice(0, item.position) + tagString + data.content.slice(item.position);
                });
            }
            if (findedMsg && findedMsg.agent_thought && findedMsg.agent_thought.files && findedMsg.agent_thought.files.length > 0) {
                data.content = this.handeFilesDownloadCards(findedMsg.agent_thought.files, data.content);
            }

            this.assembleMsgContent(data, MESSAGE_TYPE.ANSWER);
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] reply`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }

    // 监听token用量和详情事件
    listenTokenStat() {
        $s.on('token_stat', (data) => {
            $e.$emit('token_state_change', data);
            if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时，则不做处理
            let loadingMsg = cache.chatsContent.find((el) => el.loading_message);
            let loadingText = '思考中';
            // console.log('【vvvvvvvvvvvvvvvvvvvvvvvvvvv】', loadingMsg, window.webimToken[0].pattern);
            if (loadingMsg) {
                if (data.procedures && data.procedures.length > 0) {
                    loadingText =
                        data.procedures[data.procedures.length - 1].title || '思考中';
                }
                let currentList = cache.chatsContent;
                currentList.forEach((el) => {
                    if (el.loading_message) {
                        el.text = loadingText;
                        el.record_id = data.record_id;
                        el.tokens_msg = data;
                        el.is_final = false;
                        // 只有标准模式加这个 控制展示停止生成icon
                        // if (window.webimToken[0].pattern === 'standard') {
                        //     el.is_final = false;
                        // }
                    }
                });
                // console.log(
                //     'token_stat------loading------->',
                //     data,
                //     clone(cache.chatsContent)
                // );
                $e.$emit('client_msgContentChange', {
                    chatsContent: cache.chatsContent,
                    type: MESSAGE_TYPE.ANSWER
                });
            } else {
                let findedMsg = cache.chatsContent.find(
                    (el) => el.record_id === data.record_id
                );
                // console.log('token_stat-----1111111-------->', findedMsg);
                if (!findedMsg) return;
                findedMsg.tokens_msg = data;
                // console.log('token_stat-----22222222-------->', findedMsg);

                // console.log(
                //     'token_stat-----all list--===============-->',
                //     cache.chatsContent
                // );
                $e.$emit('client_msgContentChange', {
                    chatsContent: cache.chatsContent,
                    type: MESSAGE_TYPE.ANSWER
                });
            }
            // token_stat 内容太长
            // if (Vue.$aegis) {
            //     Vue.$aegis.infoAll({
            //         msg: `[socket event] reply`,
            //         level: Aegis.logType.INFO,
            //         ext1: `uin ${Cookies.get('username') || '-'}`,
            //         ext2: JSON.stringify(data)
            //     });
            // }
        });
    }
    getShowType(item) {
        // 展示种类 md json lke
        if (item.name === 'thought') {
            return 'md';
        } else if (item.status === 'success' || item.status === 'processing') {
            // 在clientData处还有特殊处理
            // 原来为lke-reference，现在区分两块处理，一块搜索类型参考来源，一块为qa doc参考来源，主要区别为字段内部数据定义和处理差异
            // 只能判断搜索 这块唯一标识取  index 将index转id
            if (item.debugging && item.debugging.display_type === 1) {
                return 'search-reference';
            } else if (item.debugging && item.debugging.display_type === 2) {
                // 只能qa和doc 这块唯一标识取  id
                return 'knowledge-reference';
            } else if (item.debugging && item.debugging.display_type === 3) {
                // 云沙盒桌面
                return 'sandbox';
            } else {
                return 'json';
            }
        } else {
            return 'json';
        }
    }
    // 给content中内容塞入小标标签的标识
    handeLittleTagsData(quote_infos, references, content) {
        let contentRes = '';
        if (quote_infos && quote_infos.length > 0) {
            const quoteMock = quote_infos.reduce((acc, curr) => {
                const existingItem = acc.find(item => item.position === curr.position);
                let res = {};
                if (references && references.length > 0) {
                    res = references.find(i => i.id === curr.index.toString());
                }
                if (existingItem) {
                    existingItem.tag.push({ ...res, id: curr.index });
                } else {
                    acc.push({
                        'tag': [{ ...res, id: curr.index }],
                        'position': curr.position
                    });
                }
                return acc;
            }, []);

            // data.quote_infos = quoteMock.sort((a, b) => b.position - a.position);
            let sortQuote = quoteMock.sort((a, b) => b.position - a.position);
            // 遍历数组，对每个元素进行操作
            contentRes = content;
            sortQuote.forEach(item => {
                // 提取id数组并转换为字符串
                const tagIds = item.tag.map(tag => tag.id);
                const tagString = `[${tagIds.join(',')}](@ref)`;

                // 在指定位置插入字符串
                contentRes = contentRes.slice(0, item.position) + tagString + contentRes.slice(item.position);
            });
            return contentRes;
        } else {
            return content;
        }
    }
    // 给content中的link类型，转换成下载卡片样式标识
    handeFilesDownloadCards(files, content) {
        // console.log('【files card】------------>', files, content);
        let res = '';
        if (files && files.length > 0) {
            const regex = /\[([^\]]+)\]\(([^)]+)\)/g;
            res = content;
            let match;
            let matchs = [];

            while ((match = regex.exec(content)) !== null) {
                // console.log('【files card】------------>match', match);

                matchs.push(match);
                // const linkText = match[1];
                // res = res.replace(match[0], `([${linkText}]@files)`);
            }
            // console.log('【files card】------------>matchs', matchs);
            // console.log('【files card】------------>1111122222', res);

            matchs.forEach(mc => {
                const findFile = files.find(f => f.file_name === mc[1] && f.file_url === mc[2]);
                // console.log('【files card】------------>findFile', findFile);

                if (findFile) {
                    res = res.replace(mc[0], `[[${findFile.id}]@file]`);
                }
            });
            // console.log('【files card】------------>res', res);
            return res;
        } else {
            // console.log('【files card】------------>11111333333333', content);
            return content;
        }
    }
    // 监听agent模式思考过程详情
    listenThought() {
        $s.on('thought', (data) => {
            if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时，则不做处理
            // let loadingMsg = cache.chatsContent.find((el) => el.loading_message);
            let findedMsg = cache.chatsContent.find(
                (el) => el.record_id === data.record_id
            );
            // console.log('【thought】-----1111111-------->', findedMsg);
            if (!findedMsg) return;
            if (data && data.files && data.files.length > 0) {
                data.files.forEach((ele, index) => {
                    ele.id = index;
                    ele.icon = getFileIcon(ele.file_type);
                    ele.iconUrl = getFileIconUrl(ele.file_type);
                });
            }
            if (data && data.procedures && data.procedures.length > 0) {
                data.procedures.forEach(el => {
                    el.show_type = this.getShowType(el);
                    if (this.getShowType(el) === 'search-reference') {
                        let quote_infos = el.debugging && el.debugging.quote_infos;
                        // 给reference备注id index
                        let references = el.debugging && el.debugging.references && el.debugging.references.map((m) => ({ ...m, id: m.index }));
                        el.debugging.references = references || [];
                        let content = el.debugging && el.debugging.display_content;
                        if (quote_infos && quote_infos.length > 0) {
                            el.display_content = this.handeLittleTagsData(quote_infos, references, content);
                        } else {
                            el.display_content = content || '';
                        }
                    } else if (this.getShowType(el) === 'knowledge-reference') {
                        // let references = el.debugging && el.debugging.references && el.debugging.references.map((m) => ({ ...m, id: m.index }));
                        // el.debugging.references = references || [];

                        let content = el.debugging && el.debugging.display_content;
                        let thought = el.debugging && el.debugging.display_thought;
                        el.display_thought = thought || '';
                        el.display_content = content || '';
                    } else {
                        let content = el.debugging && el.debugging.display_content;
                        el.display_content = content || '';
                    }
                });
            }
            findedMsg.agent_thought = data;

            // console.log(
            //     '【thought】-----all list--===============-->',
            //     cache.chatsContent
            // );
            $e.$emit('client_msgContentChange', {
                chatsContent: cache.chatsContent,
                type: MESSAGE_TYPE.ANSWER
            });
            // if (Vue.$aegis) {
            //     Vue.$aegis.infoAll({
            //         msg: `[socket event] reply`,
            //         level: Aegis.logType.INFO,
            //         ext1: `uin ${Cookies.get('username') || '-'}`,
            //         ext2: JSON.stringify(data)
            //     });
            // }
        });
    }

    async fillReferenceField(msg) {

    }

    // 监听参考来源消息
    listenReference() {
        $s.on('reference', (data) => {
            // console.log('0000000000000000ref', data);
            let findedMsg = this.getMsgById(data.record_id);
            // console.log('0000000000000000ref1', findedMsg);

            // let findedMsg = cache.chatsContent[cache.chatsContent.length - 1];
            if (findedMsg) {
                // type为4 --- 搜索引擎引用来源
                // 将问答类型的引用筛选出去
                // 用户端需要展示 3（文档类型），后台只会返回 3
                // 评测端后台会返回 1（问答类型）、2（文档分片类型），但本期不支持展示 1
                // const data1 = [
                //     {
                //         'doc_biz_id': '0',
                //         'doc_id': '0',
                //         'doc_name': '',
                //         'id': '1',
                //         'name': '奖牌统计 - 2024年巴黎奥运会奖牌榜',
                //         'qa_biz_id': '0',
                //         'type': 4,
                //         'url': 'https://www.baidu.com'
                //     },
                //     {
                //         'doc_biz_id': '0',
                //         'doc_id': '0',
                //         'doc_name': '',
                //         'id': '2',
                //         'name': '24年巴黎奥运会：中国代表团奖牌得主一览',
                //         'qa_biz_id': '0',
                //         'type': 4,
                //         'url': 'https://olympics.com/zh/news/paris-2024-team-china-medalists-overview'
                //     }
                // ];
                // findedMsg.references = data1
                findedMsg.references = data.references
                    // .filter((reference) => reference.type !== 1)
                    // 合并相同文档的参考来源
                    // 合并相同文档的参考来源
                    .reduce((result, item) => {
                        if (item.type === 4) {
                            result.push({ ...item, ids: [item.id] });
                        } else if (item.type === 1) {
                            result.push({ ...item, ids: [item.id] });
                        } else {
                            const existingItem = result.find(
                                (i) => i.doc_id === item.doc_id && i.type === item.type
                            );
                            if (existingItem) {
                                existingItem.ids.push(item.id);
                            } else {
                                result.push({ ...item, ids: [item.id] });
                            }
                        }
                        return result;
                    }, []);
                // console.log('0000000000000000ref2', findedMsg, cache.chatsContent);

                // console.log('ws msg---->', findedMsg, cache.chatsContent);
                this.fillReferenceField(findedMsg);
                $e.$emit('client_msgContentChange', {
                    chatsContent: cache.chatsContent,
                    type: MESSAGE_TYPE.REFERENCE // ”参考来源“事件
                });
            }
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] reference`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }

    // 监听recommended推荐问
    listenRecommended() {
        $s.on('recommended', (data) => {
            // console.log('recommended--------》0', data);
            let findedMsg = this.getMsgById(data.record_id);
            // console.log('recommended---------》1', findedMsg);
            if (findedMsg && data.recommendeds) {
                findedMsg.recommended = data.recommendeds;
                // console.log('recommended---------》1', findedMsg, cache.chatsContent);
                $e.$emit('client_msgContentChange', {
                    chatsContent: cache.chatsContent,
                    type: MESSAGE_TYPE.REFERENCE // ”参考来源“事件
                });
            }
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] recommended`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }

    listenShowSearchEngine() {
        $s.on('show_search_engine', (data) => {
            // cache.configInfo.show_search_engine = data.show_search_engine;
            // console.log('on show_search_engine', data);
            // console.log('show_search_engine', data, clone(cache.chatsContent));
            if (data.show_search_engine) {
                let currentList = cache.chatsContent;
                currentList.forEach((el) => {
                    if (el.loading_message) {
                        el.text = '正在为您检索搜索引擎';
                    }
                });
                $e.$emit('client_msgContentChange', {
                    chatsContent: cache.chatsContent,
                    type: MESSAGE_TYPE.ANSWER
                });
            }
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] show_search_engine`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }

    // 监听参考来源消息
    // listenReference () {
    //     $s.on('reference', (data) => {
    //         const findedMsg = this.getMsgById(data.record_id);
    //         if (findedMsg) {
    //             // 将问答类型的引用筛选出去
    //             // 用户端需要展示 3（文档类型），后台只会返回 3
    //             // 评测端后台会返回 1（问答类型）、2（文档分片类型），但本期不支持展示 1
    //             findedMsg.references = data.references
    //                 .filter((reference) => reference.type !== 1)
    //                 // 合并相同文档的参考来源
    //                 .reduce((result, item) => {
    //                     const existingItem = result.find(i => i.doc_id === item.doc_id);
    //                     if (existingItem) {
    //                         existingItem.ids.push(item.id);
    //                     } else {
    //                         result.push({ ...item, ids: [item.id] });
    //                     }
    //                     return result;
    //                 }, []);
    //             $e.$emit('client_msgContentChange', {
    //                 chatsContent: cache.chatsContent,
    //                 type: MESSAGE_TYPE.REFERENCE // ”参考来源“事件
    //             });
    //         }
    //     });
    // }

    // 监听点赞/点踩回执
    listenFeedback() {
        $s.on('rating', (data) => {
            const findedMsg = this.getMsgById(data.record_id);

            if (findedMsg) {
                findedMsg.score = data.score;
                findedMsg.reasons = data.reasons;

                $e.$emit('client_msgContentChange', {
                    chatsContent: cache.chatsContent,
                    type: MESSAGE_TYPE.FEEDBACK // ”点赞/点踩回执“事件
                });
            }
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] rating`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }
    // 监听会话转接事件
    listenSessionTransfer() {
        $s.on('transfered', (data) => {
            if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时，则不做处理
            let currentList = cache.chatsContent;
            currentList[currentList.length - 1].transfer = true; // 消息队列中最新一条数据打上 transfer 标记
            currentList[currentList.length - 1].transferRobot = false; // 消息队列中最新一条数据打上 quit 标记
            currentList[currentList.length - 1].avatar = data.avatar; // 转接后的人工客服头像
            this.assembleMsgContent(
                currentList[currentList.length - 1],
                MESSAGE_TYPE.ANSWER
            );

            cache.transferInfo.transferStatus = true;
            cache.transferInfo.transferAvatar = data.avatar;
            $e.$emit('data_transferInfo', cache.transferInfo);
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] transfered`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }
    // 监听会话重制事件
    listenSessionReset() {
        $s.on('session_reset', (data) => {
            // console.log('session_reset---->', data, cache);
            if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时，则不做处理
            // 重置会话
            if (!data.session_disassociated_timestamp) {
                cache.session_id = 0;
                cache.configInfo.session_id = 0;
            }
            $e.$emit('data_session_reset', data);
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] session_reset`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }
    // 监听会话结束事件
    listenSessionClosed() {
        $s.on('session_closed', (data) => {
            if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时，则不做处理
            let currentList = cache.chatsContent;
            currentList[currentList.length - 1].quit = true; // 消息队列中最新一条数据打上 quit 标记
            // currentList[currentList.length - 1].transferRobot = true; // 消息队列中最新一条数据打上 quit 标记
            this.assembleMsgContent(
                currentList[currentList.length - 1],
                MESSAGE_TYPE.ANSWER
            );
            // 刷新转人工的状态
            // this.getTransferStatus();
            if (Vue.$aegis) {
                Vue.$aegis.infoAll({
                    msg: `[socket event] session_closed`,
                    level: Aegis.logType.INFO,
                    ext1: `uin ${Cookies.get('username') || '-'}`,
                    ext2: JSON.stringify(data)
                });
            }
        });
    }
    // 组装消息队列数据
    // 问题确认消息：根据request_id关联覆盖（服务端收到问题后的确认消息）
    // 答案消息：倒序遍历插入（服务端答案消息）
    assembleMsgContent(msgList, type, options = {}) {
        // console.log(
        //     'transfered transfered',
        //     type,
        //     clone(msgList),
        //     clone(cache.chatsContent)
        // );
        let newMsg = msgList;

        if (type === MESSAGE_TYPE.QUESTION) {
            // 发送的问题消息由前端临时插入消息队列
            cache.chatsContent.push(newMsg);
        } else if (type === MESSAGE_TYPE.ANSWER) {
            // console.log('transfered 1 transfered', type, clone(msgList), clone(cache.chatsContent));
            if (cache.chatsContent.length < 1) {
                cache.chatsContent.push(newMsg);
            } else {
                let currentList = cache.chatsContent;

                timeoutTasks[newMsg.request_id] &&
                    clearTimeout(timeoutTasks[newMsg.request_id]);

                if (currentList.length === 2 && newMsg.can_rating) {
                    currentList[0].transferRobot = true;
                }
                if (newMsg.transfer && newMsg.loading_message) {
                    // console.log('newMsg.transfer && newMsg.loading_message');
                    currentList.pop();
                    currentList[currentList.length - 1].loading_message = false;
                    currentList[currentList.length - 1] = {
                        ...newMsg,
                        ...currentList[currentList.length - 1],
                        transfer: true,
                        transferRobot: false
                    };
                } else {
                    // console.log('transfered 2 transfered', type, currentList, clone(msgList), clone(cache.chatsContent));
                    const reqid = currentList.find((i) => {
                        return i.request_id === newMsg.request_id;
                    });
                    for (let i = currentList.length - 1; i >= 0; i--) {
                        const { transfer, quit, transferRobot } = currentList[i];
                        let tmp = {
                            ...newMsg,
                            transfer,
                            quit,
                            transferRobot
                        };
                        // 保留tokens_msg，防止覆盖
                        if (currentList[i].tokens_msg) {
                            tmp = { ...tmp, tokens_msg: currentList[i].tokens_msg };
                        }
                        // 保留thought 放置被覆盖
                        if (currentList[i].agent_thought) {
                            tmp = { ...tmp, agent_thought: currentList[i].agent_thought };
                        }
                        // 保留reference
                        if (currentList[i].references) {
                            tmp = { ...tmp, references: currentList[i].references };
                        }
                        // 答案消息流式输出覆盖（record_id）
                        if (newMsg.record_id === currentList[i].record_id) {
                            // console.log('案消息流式输出覆盖（record_id）');
                            // 澄清询问需要将链接摘出来当做问题交互
                            currentList[i] = {
                                ...tmp,
                                ...getClarifyQuestion(newMsg)
                            };
                            break;
                        }
                        if (newMsg.request_id && newMsg.is_from_self) {
                            // console.log(
                            //     '案消息流式输出覆盖（record_id） newMsg.is_from_self'
                            // );
                            if (reqid && newMsg.request_id === currentList[i].request_id) {
                                newMsg.is_loading = false; // 服务端确认收到问题消息，则去除”发送中“状态
                                currentList[i] = tmp;
                            } else {
                                currentList.push(tmp);
                            }
                            // 非人工状态时, 并且用户发送的不是敏感消息。插入临时[正在思考中...]消息
                            if (!newMsg.is_evil && !cache.transferInfo.transferStatus) {
                                currentList.push({
                                    // show_search_engine: cache.configInfo.show_search_engine,
                                    loading_message: true,
                                    is_from_self: false,
                                    content: '',
                                    from_avatar: cache.configInfo.avatar,
                                    // timestamp: Math.floor(+new Date() / 1000) // 精确到秒
                                    timestamp: Number(currentList[i].timestamp) // 精确到秒
                                });
                            }
                            break;
                        }
                        // 插入最新答案消息
                        // TODO 修复正在思考中的问题。
                        // console.log(
                        //     '清理正在思考的判断',
                        //     Number(newMsg.timestamp),
                        //     Number(currentList[i].timestamp)
                        // );
                        if (Number(newMsg.timestamp) >= Number(currentList[i].timestamp)) {
                            // console.log(
                            //     '案消息流式输出覆盖（record_id） newMsg.is_from_self'
                            // );
                            if (currentList[i].loading_message) {
                                // 删除原来的[正在思考中...]消息
                                if (currentList[i].tokens_msg) {
                                    if (
                                        currentList[i].tokens_msg.record_id === newMsg.record_id
                                    ) {
                                        newMsg = {
                                            ...newMsg,
                                            tokens_msg: currentList[i].tokens_msg
                                        };
                                    }
                                }
                                console.error(
                                    'token_stat---del---loading------->',
                                    currentList[i],
                                    newMsg
                                );
                                currentList[currentList.length - 1] = newMsg;
                                // currentList.splice(i, 1, newMsg);
                            } else {
                                // console.log('token_stat---del---loading----2--->', currentList[i], newMsg);
                                currentList.splice(i + 1, 0, newMsg);
                            }
                            break;
                        }
                        if (
                            i === 0 &&
                            Number(newMsg.timestamp) < Number(currentList[i].timestamp)
                        ) {
                            // console.log('token_stat---del---loading---3---->', currentList[i], newMsg);
                            currentList.splice(0, 0, newMsg);
                        }
                    }
                }
            }
        } else if (type === MESSAGE_TYPE.HISTORY) {
            let currentList = cache.chatsContent;
            
            // 历史数据打上标签，无需展示”重新生成“和”停止生成“操作
            msgList = msgList.map((r) => {
                // let res = r.references.filter((reference) => reference.type !== 1).reduce((result, item) => {
                
                if (r.quote_infos && r.quote_infos.length > 0) {
                    const quoteMock = r.quote_infos.reduce((acc, curr) => {
                        const existingItem = acc.find(item => item.position === curr.position);
                        let ret = {};
                        if (r && r.references && r.references.length > 0) {
                            ret = r.references.find(i => i.id === curr.index.toString());
                        }
                        if (existingItem) {
                            existingItem.tag.push({ ...ret, id: curr.index });
                        } else {
                            acc.push({
                                'tag': [{ ...ret, id: curr.index }],
                                'position': curr.position
                            });
                        }
                        return acc;
                    }, []);
                    r.quote_infos = quoteMock.sort((a, b) => b.position - a.position);
                    // 遍历数组，对每个元素进行操作
                    r.quote_infos.forEach(item => {
                        // 提取id数组并转换为字符串
                        const tagIds = item.tag.map(tag => tag.id);
                        const tagString = `[${tagIds.join(',')}](@ref)`;
                        // 在指定位置插入字符串
                        r.content = r.content.slice(0, item.position) + tagString + r.content.slice(item.position);
                    });
                }
                // 处理思考部分
                if (r.agent_thought && r.agent_thought.procedures && r.agent_thought.procedures.length > 0) {
                    r.agent_thought.procedures.forEach(el => {
                        el.show_type = this.getShowType(el);
                        if (this.getShowType(el) === 'search-reference') {
                            let quote_infos = el.debugging && el.debugging.quote_infos;
                            let references = el.debugging && el.debugging.references && el.debugging.references.map((m) => ({ ...m, id: m.index }));
                            el.debugging.references = references || [];

                            // let content = el.debugging && el.debugging.display_content;
                            // el.display_content = this.handeLittleTagsData(quote_infos, references, content);
                            let content = el.debugging && el.debugging.display_content;
                            if (quote_infos && quote_infos.length > 0) {
                                el.display_content = this.handeLittleTagsData(quote_infos, references, content);
                            } else {
                                el.display_content = content || '';
                            }
                        } else {
                            let content = el.debugging && el.debugging.display_content;
                            el.display_content = content || '';
                        }
                    });
                }
                if (r.agent_thought && r.agent_thought.files && r.agent_thought.files.length > 0) {
                    r.agent_thought.files.forEach((ele, index) => {
                        ele.id = index;
                        ele.icon = getFileIcon(ele.file_type);
                        ele.iconUrl = getFileIconUrl(ele.file_type);
                    });
                }

                // 处理文件下载card
                if (r.agent_thought && r.agent_thought.files) {
                    r.content = this.handeFilesDownloadCards(r.agent_thought.files, r.content);
                }

                if (
                    cache.app_type === APP_TYPE.CLASSIFYS &&
                    !r.is_from_self &&
                    r.type !== 6
                ) {
                    if (isJSON(r.content)) {
                        r.tags = JSON.parse(r.content);
                        r.content = '';
                    }
                }
                return {
                    ...r,
                    is_history: true,
                    is_final: true
                };
            });
            if (currentList.length === 0) {
                // 若消息队列为空（用户端，初始拉取历史记录，用做判断欢迎页展示场景）
                cache.chatsContent = [].concat(msgList);
            } else {
                // 若消息队列不为空
                let oldMsgCurrent = currentList[0];
                let newMsgHistory = msgList[msgList.length - 1];

                // 将历史数据拼装到消息队列中（按照时间戳重排数据）
                if (
                    newMsgHistory &&
                    oldMsgCurrent &&
                    Number(newMsgHistory.timestamp) < Number(oldMsgCurrent.timestamp)
                ) {
                    cache.chatsContent = [].concat(msgList).concat(cache.chatsContent);
                } else {
                    msgList.reverse().forEach((msg) => {
                        for (let i = 0; i < cache.chatsContent.length; i++) {
                            if (msg.record_id === cache.chatsContent[i].record_id) {
                                // 重复覆盖
                                cache.chatsContent[i] = msg;
                                break;
                            } else if (
                                Number(msg.timestamp) <= Number(cache.chatsContent[i].timestamp)
                            ) {
                                cache.chatsContent.splice(i, 0, msg);
                                break;
                            } else if (
                                i === cache.chatsContent.length - 1 &&
                                Number(msg.timestamp) > Number(cache.chatsContent[i].timestamp)
                            ) {
                                cache.chatsContent.splice(i + 1, 0, msg);
                            }
                        }
                    });
                }
            }
        }

        // 消息去重。同一record_id取最新，同时保留消息最早的时间戳
        cache.chatsContent = arrayUnique(
            cache.chatsContent,
            'record_id',
            'timestamp'
        );

        // console.log('==【用户端】消息队列 == \n', {
        //     chatsContent: cache.chatsContent,
        //     type
        // });

        // 消息队列变更通知事件
        $e.$emit('client_msgContentChange', {
            chatsContent: cache.chatsContent,
            type,
            options
        });
    }
    // 修改指定msgId的消息内容
    modifyMsgContent(msgId, surfix = '已停止生成', manual = true) {
        const findedMsg = this.getMsgById(msgId);

        if (findedMsg) {
            if (manual) {
                // 假如后台没有返回
                setTimeout(() => {
                    findedMsg.is_final = true;
                }, 2000);
                // } else {
                // 网络问题终止加个标志位
                // findedMsg.is_connection_error = true;
            }
            // 正则表达式匹配 "```" 字符
            const regex = /```/g;

            // console.log('regex.test(findedMsg.content)', regex.test(findedMsg.content));
            // 使用 match 方法找到所有 "```" 的匹配项
            const matches = findedMsg.content.match(regex);

            // 计算 "```" 的出现次数
            const count = matches ? matches.length : 0;

            // 判断 "```" 的数量是否为奇数
            if (count % 2 !== 0) {
                // 如果是奇数，在末尾添加 "```  \n\n 已停止生成"
                findedMsg.content = findedMsg.content.concat(
                    '\n ```  \n\n' + `<span class="stop-ws">| ${surfix}</span>`
                );
            } else {
                // 如果是偶数，在末尾添加 "  \n\n 已停止生成"
                // findedMsg.content = findedMsg.content.concat(
                //   `<span class="stop-ws">| ${surfix}</span>`
                // );
                if (findedMsg.content) {
                    findedMsg.content = findedMsg.content.concat(
                        `<span class="stop-ws">| ${surfix}</span>`
                    );
                } else {
                    findedMsg.content = findedMsg.content;
                }
            }
            $e.$emit('client_msgContentChange', {
                chatsContent: cache.chatsContent,
                type: MESSAGE_TYPE.STOP // ”停止生成“事件
            });
        }
    }
    // 获取消息队列数据
    getChatsContent() {
        return cache.chatsContent || [];
    }
    // 根据msgId获取消息
    getMsgById(msgId) {
        const findedMsg = cache.chatsContent.find((r) => r.record_id === msgId);
        return findedMsg;
    }
    // 根据msgId获取其关联问题消息
    getQmsgById(msgId) {
        let findedQmsg = null;
        const findedMsg = this.getMsgById(msgId);

        if (findedMsg) {
            findedQmsg = cache.chatsContent.find(
                (r) => r.record_id === findedMsg.related_record_id
            );
        }

        return findedQmsg;
    }
    // 查询历史消息记录 isScroll 表示是否下拉获取数据，如果是的话，不需要滚动
    convertKeys(obj) {
        if (typeof obj !== 'object' || obj === null) {
            return obj;
        }
        
        if (Array.isArray(obj)) {
            return obj.map(item => this.convertKeys(item));
        }
        
        const newObj = {};
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
            // 转换键名
            const newKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
            // 处理连续下划线或开头下划线的情况
            const finalKey = newKey.replace(/^_+|_+$/g, '').replace(/_+/g, '_');
            
            // 递归处理值
            newObj[finalKey] = this.convertKeys(obj[key]);
            }
        }
        return newObj;
    }
    async getHistory(isScroll, signal) {
        if (!cache.configInfo || !cache.configInfo.session_id) {
            $e.$emit('data_historyError');
        } else {
            
            let botid = window.localStorage.getItem('bot_biz_id_im');
            const sssId = cache.configInfo.session_id
            const res = await getMsgRecord(botid,HISTORY_COUNT,sssId);
            
            if(res.status == 200){
                const newRes = this.convertKeys(res.data);
                if (newRes.records) {
                    let list = newRes.records;
                    if (newRes.session_disassociated_timestamp && newRes.session_disassociated_timestamp > 0 && newRes.records.length > 0) {

                        const index = list.findIndex(
                            (item) =>
                                item.Timestamp > newRes.session_disassociated_timestamp / 1000
                        );
                        if (index === -1) {
                            list[list.length - 1].isBreakReleation = true;
                        } else {
                            list[index].isBreakReleationTop = true;
                        }
                    }
                    list = list.map((r) => {
                        return {
                            ...r,
                            tokens_msg: r.token_stat,
                            ...getClarifyQuestion(r)
                        };
                    });
                    // 停止语音通话 增加标识位
                    if (signal === 'stopVoice' && list[list.length - 1]) {
                        list[list.length - 1].stopVoice = true;
                    }
                    // console.log(list,'listlistlist')
                    this.assembleMsgContent(list, MESSAGE_TYPE.HISTORY, { isScroll });
                } else if (newRes.code === 460006) {
                    // 消息被清空了。
                    this.assembleMsgContent([], MESSAGE_TYPE.HISTORY, { isScroll });
                } else {
                    $e.$emit('data_historyError');
                    console.log('获取历史记录失败，请重试！');
                    Vue.prototype.$message.error('获取历史记录失败，请重试！');
                }
                $e.$emit('data_history', cache.chatsContent);
                if (!isScroll) {
                    const payload = JSON.stringify({
                        from: 'webim',
                        type: 'history-ready'
                    });
                    window.parent.postMessage(payload, '*');
                }
            }
        }
    }
    // 停止生成回复
    stopGeneration(msg, manual = true) {
        // console.log('stopGeneration', 'stop', msg, manual, cache.chatsContent);
        // console.log('stopGeneration stopGeneration');
        // console.log({ chatsContent: cache.chatsContent });
        /**
     * 如果存在网络错误导致的中断消息，从上往下查找未结束的消息，会命中网络错误中断消息，从而导致状态设置出错
     * 因此从后往前查找未结束的消息并停止
     */
        const findArr = cache.chatsContent.filter((r) => r.is_final === false);
        const ongoingMsg = findArr[findArr.length - 1];

        if (!ongoingMsg) return;

        $s.emit('stop_generation', {
            record_id: ongoingMsg.record_id
        });
        if (Vue.$aegis) {
            Vue.$aegis.infoAll({
                msg: `[socket event] stop_generation`,
                level: Aegis.logType.INFO,
                ext1: `uin ${Cookies.get('username') || '-'}`,
                ext2: JSON.stringify({
                    record_id: ongoingMsg.record_id
                })
            });
        }
        this.modifyMsgContent(ongoingMsg.record_id, msg, manual);
    }
    // 监听ws报错
    listenError() {
        const SYSTEMEVENTS = [
            'connect', // 连接成功
            'connectError', // 连接错误
            'error', // 请求错误
            'disconnect', // 连接异常中断
            'SocketError', // 连接请求错误
            'reconnect', // 重新连接
            'reconnectAttempt', // 重新连接
            'reconnectError', // 重新连接错误
            'reconnectFailed' // 重新连接失败
        ];

        SYSTEMEVENTS.forEach((eventName) => {
            $s.on(eventName, (data) => {
                // this.setSystemEvents([eventName, data]);
                // $e.$emit('client_systemEvents', this.getSystemEvents());
                // console.log(
                //     'token_stat-----------listen_error',
                //     eventName,
                //     data,
                //     clone(cache.chatsContent)
                // );
                $e.$emit('client_systemEvents', data);
                if (cache.chatsContent &&
                    cache.chatsContent[cache.chatsContent.length - 1]) {
                    const lastCacheContent = cache.chatsContent[cache.chatsContent.length - 1];
                    if ((!lastCacheContent.is_final ||
                        lastCacheContent.is_loading) &&
                        eventName === 'disconnect') {
                        // Vue.prototype.$message.error('网络问题，链接已断开，请重试。');
                        if (Vue.$aegis) {
                            Vue.$aegis.infoAll({
                                msg: `[socket event] ${eventName} 消息未输出完全就断开！`,
                                level: Aegis.logType.INFO,
                                ext1: `uin ${Cookies.get('username') || '-'}`,
                                ext2: JSON.stringify(data)
                            });
                        }
                    }
                    if ((!lastCacheContent.is_final ||
                        lastCacheContent.is_loading) &&
                        eventName === 'connect') {
                        // console.log('eventName msg_reconnect', data, eventName);
                        let request_id = lastCacheContent.request_id;
                        let session_id = lastCacheContent.session_id;
                        if (lastCacheContent.agent_thought) {
                            request_id = lastCacheContent.agent_thought.request_id;
                            session_id = lastCacheContent.agent_thought.session_id;
                        }
                        if (lastCacheContent.tokens_msg) {
                            request_id = lastCacheContent.tokens_msg.request_id;
                            session_id = lastCacheContent.tokens_msg.session_id;
                        }
                        const parma = {
                            request_id,
                            session_id
                        };
                        if (lastCacheContent.is_from_self) {
                            parma.related_record_id = lastCacheContent.related_record_id;
                        } else {
                            parma.record_id = lastCacheContent.record_id;
                        }
                        if (parma.related_record_id || parma.record_id) {
                            $s.emit('msg_reconnect', parma);
                        }
                        if (Vue.$aegis) {
                            Vue.$aegis.infoAll({
                                msg: `[socket event] ${eventName} 消息未输出完全就断开，发送reconnect消息！`,
                                level: Aegis.logType.INFO,
                                ext1: `uin ${Cookies.get('username') || '-'}`,
                                ext2: JSON.stringify({
                                    request_id: lastCacheContent.request_id,
                                    session_id: lastCacheContent.request_id,
                                    record_id: lastCacheContent.request_id,
                                    related_record_id: lastCacheContent.related_record_id
                                })
                            });
                        }
                    }

                    if (lastCacheContent.is_loading &&
                        eventName === 'error') {
                        // cache.chatsContent.pop();
                        const findItem = cache.chatsContent.find((el) => el.is_loading);
                        if (findItem) {
                            delete findItem.is_loading;
                            findItem.failed = true;
                        }

                        // 消息队列变更通知事件
                        $e.$emit('client_msgContentChange', {
                            chatsContent: cache.chatsContent,
                            type: MESSAGE_TYPE.ANSWER
                        });
                    }
                    if (lastCacheContent.loading_message &&
                        eventName === 'error'
                    ) {
                        // cache.chatsContent.pop();
                        const findItem = cache.chatsContent.find((el) => el.loading_message);
                        if (findItem) {
                            delete findItem.loading_message;
                            // findItem.is_final = true;
                        }

                        // 消息队列变更通知事件
                        $e.$emit('client_msgContentChange', {
                            chatsContent: cache.chatsContent,
                            type: MESSAGE_TYPE.ANSWER
                        });
                    }
                }
                if (Vue.$aegis) {
                    Vue.$aegis.infoAll({
                        msg: `[socket event] ${eventName}`,
                        level: Aegis.logType.INFO,
                        ext1: `uin ${Cookies.get('username') || '-'}`,
                        ext2: JSON.stringify(data)
                    });
                }
            });
        });
    }
    setSystemEvents(data) {
        cache.systemEvents.unshift(data);
        if (cache.systemEvents.length > systemEventsMax) {
            cache.systemEvents.length = systemEventsMax;
        }
    }
    hadRetryQa(id) {
        // console.log('hadRetryQa', id, clone(cache.chatsContent))
        const findedMsg = this.getMsgById(id);
        if (findedMsg) {
            // findedMsg.hadRetryQa = true
            findedMsg.had_retry_qa = true;
            $e.$emit('client_msgContentChange', {
                chatsContent: cache.chatsContent,
                type: MESSAGE_TYPE.ANSWER
            });
        }
        // console.log('hadRetryQa---change------------>', id, clone(cache.chatsContent))
    }
    getSystemEvents() {
        return cache.systemEvents;
    }
    breakReleation(val) {
        // console.log('breakReleation---->', val);
        let list = cache.chatsContent;
        // list[list.length - 1].isBreakReleation = true;

        const index = list.findIndex((item) => item.timestamp > val / 1000);
        if (index === -1) {
            list[list.length - 1].isBreakReleation = true;
        } else {
            list[index].isBreakReleationTop = true;
        }

        // console.log('是否仅清空会话关联 -----2>', cache.chatsContent);
        $e.$emit('client_msgContentChange', {
            chatsContent: cache.chatsContent,
            type: MESSAGE_TYPE.ANSWER
        });
    }
    async modifyUserDialogConfig(options) {
    }
    updateReadStatus(data) {
        // reading_audio事件参数 reading-停止(0)还是开始（1），msg-播放时的数据，id-record_id
        const before = { ...cache.readingInfo };
        if (data.reading) {
            if (data.msg) {
                cache.readingInfo = { is_reading: true, record_id: data.msg.record_id };
            }
        } else {
            if (data.msg && data.msg.record_id) {
                // 带id要看是当前在播放是否是这个 id
                if (cache.readingInfo.is_reading && data.msg.record_id === cache.readingInfo.record_id) {
                    cache.readingInfo = { is_reading: false, record_id: '' };
                }
            } else {
                // 不带 id 直接停止所有，
                cache.readingInfo = { is_reading: false, record_id: '' };
            }
        }
        // console.log('tts:reading_audio-before', before, 'after', cache.readingInfo, 'data', data);
    }
    getReadStatus() {
        return cache.readingInfo;
    }
    // 清空消息队列
    clearCache() {
        cache.chatsContent = [];
        localStorage.setItem("thissessionid","");
        window.location.reload();
    }
    releaseCache() { }
    destroy() {
        // be careful to clear the cache to avoid errors
        this.releaseCache();
    }
}

const $cd = new ClientData();
Vue.prototype.$clientData = $cd;
export default $cd;